cmake_minimum_required(VERSION 3.10)
project(ANICOOKBOOK)

# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# 查找 ets_compiler
if(DEFINED ENV{PANDA_HOME})
    # 如果环境变量 ETS_COMPILER_PATH 存在，将其添加到搜索路径
    list(APPEND CMAKE_PROGRAM_PATH $ENV{PANDA_HOME}/bin)
endif()

find_program(ETS_COMPILER es2panda)
find_program(ETS_RUNTIME ark)
find_program(ETS_DISASM ark_disasm)

if(NOT ETS_COMPILER)
    message(FATAL_ERROR "ets_compiler not found! Please set ETS_COMPILER_PATH or ensure ets_compiler is in your PATH.")
else()
    message(STATUS "Found ets_compiler: ${ETS_COMPILER}")
endif()

# 自定义ETS构建规则
function(build_ets_target target_name ets_files output_name)
    
    # 设置输出目录
    set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/output")

    # 创建输出目录（如果不存在）
    file(MAKE_DIRECTORY ${OUTPUT_DIR})
    
    add_custom_command(
        OUTPUT ${OUTPUT_DIR}/${output_name}.abc  # 输出文件
        COMMAND ${ETS_COMPILER} ${ets_files} --output ${OUTPUT_DIR}/${output_name}.abc #--extension sts  # 生成命令
        DEPENDS ${ets_files}  # 输入文件依赖
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}  # 工作目录
        COMMENT "Building ETS target ${target_name}"  # 注释
    )

    add_custom_command(
        OUTPUT  ${OUTPUT_DIR}/${output_name}.abc.dump   # 输出文件
        COMMAND ${ETS_DISASM} ${OUTPUT_DIR}/${output_name}.abc  ${OUTPUT_DIR}/${output_name}.abc.dump
        DEPENDS ${OUTPUT_DIR}/${output_name}.abc   # 输入文件依赖
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}  # 工作目录
        COMMENT "Building ETS target DISASM ${target_name}"  # 注释
    )

    add_custom_target( ${target_name} 
    DEPENDS ${OUTPUT_DIR}/${output_name}.abc
    DEPENDS ${OUTPUT_DIR}/${output_name}.abc.dump  # 目标依赖于输出文件
)


endfunction()

function(run_abc target_name)

    # 设置输出目录
    set(OUTPUT_DIR "${CMAKE_BINARY_DIR}/output")
    # 创建输出目录（如果不存在）
    file(MAKE_DIRECTORY ${OUTPUT_DIR})
   
   
    add_custom_target(${target_name}
        WORKING_DIRECTORY ${OUTPUT_DIR}
        COMMAND LD_LIBRARY_PATH=${OUTPUT_DIR} ${ETS_RUNTIME} --boot-panda-files=$ENV{PANDA_HOME}/plugins/ets/etsstdlib.abc --load-runtimes=ets ${target_name}.abc ${target_name}.ETSGLOBAL::main
        COMMENT "Running ${target_name}.bac with LD_LIBRARY_PATH set to ${OUTPUT_DIR}"
    )
endfunction()


set(ANI_HEADER $ENV{PANDA_HOME}/../plugins/ets/runtime/ani)
if(NOT ANI_HEADER)
    message(FATAL_ERROR "Cannot find the path: $ENV{PANDA_HOME}/../plugins/ets/runtime/ani")
endif()

function(add_ani_demo this_target_name)
    
    set(ETS_FILES ${this_target_name}.ets)

    build_ets_target(${this_target_name}_abc ${ETS_FILES} ${this_target_name})

    add_library(${this_target_name}_cpp SHARED ${this_target_name}.cpp)

    target_compile_options(${this_target_name}_cpp
    PRIVATE  "-Wall" "-Wextra"  "-g"
    )

    set_target_properties(${this_target_name}_cpp PROPERTIES
        OUTPUT_NAME ${this_target_name}
        LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output
        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output
    )

    target_include_directories(${this_target_name}_cpp
    PUBLIC
        ${ANI_HEADER}
    )
    run_abc(${this_target_name})

    add_dependencies(${this_target_name} ${this_target_name}_cpp ${this_target_name}_abc)

endfunction()


add_ani_demo(hello_ani)


# 包含子目录
add_subdirectory(ani_interface)
add_subdirectory(ani_bigint)
add_subdirectory(ani_optional_parameter)
add_subdirectory(ani_record)
add_subdirectory(ani_template)
add_subdirectory(ani_wantpara)
add_subdirectory(ani_call_method)
add_subdirectory(ani_fast_call)
add_subdirectory(ani_async_wrapper)
add_subdirectory(ani_wrap_native_ptr)
add_subdirectory(ani_promise)
add_subdirectory(ani_setfield)
add_subdirectory(ani_union)
add_subdirectory(ani_typealias)
add_subdirectory(ani_array)
add_subdirectory(ani_enum)


add_subdirectory(ani_fn_object)
add_subdirectory(ani_string)
add_subdirectory(ani_arraybuffer)
add_subdirectory(ani_property)
add_subdirectory(ani_boxed_Double)
add_subdirectory(ani_error)

add_subdirectory(ani_boxed_Int)
add_subdirectory(ani_serialize)








